package cn.easyutil.util.javaUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;

/** 日期时间处理工具 */
public class DateUtil {
	/** 一分钟毫秒数*/
	public static final long oneMinuteTime = 1000*60;
	/** 一小时毫秒数*/
	public static final long oneHourTime = oneMinuteTime*60;
	/** 一天的毫秒数 */
	public static final long oneDayTime = oneHourTime*24;
	/** 一周毫秒数*/
	public static final long oneWeekTime = oneDayTime*7;

	/** yy/MM/dd*/
	public static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat("yy/MM/dd");
	/** yyyy-MM-dd*/
	public static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd");
	/** yyyyMM*/
	public static final SimpleDateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyyMM");
	/** yyyyMMddHHmmss*/
	public static final SimpleDateFormat DATE_FORMAT_3 = new SimpleDateFormat("yyyyMMddHHmmss");
	/** yyyy-MM-dd HH:mm:ss*/
	public static final SimpleDateFormat DATE_FORMAT_4 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/** yyyyMMddHHmmssSSS*/
	public static final SimpleDateFormat DATE_FORMAT_5 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    /** yyyy-MM-dd_HH*/
    public static final SimpleDateFormat DATE_FORMAT_6 = new SimpleDateFormat("yyyy-MM-dd_HH");
    /** yyyyMMdd*/
	public static final SimpleDateFormat DATE_FORMAT_7 = new SimpleDateFormat("yyyyMMdd");

	
	private final static String[] constellationArr = new String[] { "摩羯座", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座" };
	private final static int[] dayArr = new int[] { 20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22 };
	
	/**
     * 查询星座
     * @param timeStamp
     * @return
     */
    public static String getConstellation(long timeStamp) {
        int day =0,month = 0;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM:dd");
        String format = simpleDateFormat.format(timeStamp);
        String[] strings = format.split(":");
        month = Integer.parseInt(strings[0]);
        day = Integer.parseInt(strings[1]);
        return day < dayArr[month - 1] ? constellationArr[month - 1] : constellationArr[month];
    }
	
    /**
     * 查询星座
     * @return
     */
    public static String getConstellation(){
    	return getConstellation(System.currentTimeMillis());
    }
    
	/**
	 * 计算时间(计算传入时间前几天或者后几天的时间)
	 * @param nowTime	传入时间
	 * @param addNum	要增加的天数(为负数则是减少的天数)
	 * @return	计算后的时间
	 */
	public static long sumDay(long nowTime, int day) {
		return nowTime + (oneDayTime*day);
	}
	/**
	 * 获取几月后或前的时间戳
	 * @param time
	 * @param month
	 * @return
	 */
	public static long sumMonth(long time,int month){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date(time)); // 设置为当前时间
		calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + month);
		Date date = calendar.getTime();
		return date.getTime();
	}
	/**
	 * 获取几周后或前的时间戳
	 * @param time
	 * @param month
	 * @return
	 */
	public static long sumWeek(long time,int week){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date(time)); // 设置为当前时间
		calendar.set(Calendar.WEEK_OF_YEAR, calendar.get(Calendar.WEEK_OF_YEAR) + week);
		Date date = calendar.getTime();
		return date.getTime();
	}
	/**
	 * 获取几年后或前的时间戳
	 * @param time
	 * @param month
	 * @return
	 */
	public static long sumYear(long time,int year){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date(time)); // 设置为当前时间
		calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + year);
		Date date = calendar.getTime();
		return date.getTime();
	}
	/**
	 * 获取星期几
	 * @return
	 */
	public static int getYear(){
		return getYear(System.currentTimeMillis());
	}
	/**
	 * 获取星期几
	 * @return
	 */
	public static int getYear(long time){
		String[] strs = format(DATE_FORMAT_1,time).split("-");
		return LocalDate.of(Integer.valueOf(strs[0]), Integer.valueOf(strs[1]), Integer.valueOf(strs[2])).getYear();
	}
	/**
	 * 获取星期几
	 * @return
	 */
	public static int getWeek(){
		return getWeek(System.currentTimeMillis());
	}
	/**
	 * 获取星期几
	 * @return
	 */
	public static int getWeek(long time){
		String[] strs = format(DATE_FORMAT_1,time).split("-");
		return LocalDate.of(Integer.valueOf(strs[0]), Integer.valueOf(strs[1]), Integer.valueOf(strs[2])).getDayOfWeek().getValue();
	}
	/**
	 * 获取月份
	 * @param time	时间戳
	 * @return
	 */
	public static int getMonth(long time){
		String[] strs = format(DATE_FORMAT_1,time).split("-");
		return LocalDate.of(Integer.valueOf(strs[0]), Integer.valueOf(strs[1]), Integer.valueOf(strs[2])).getMonthValue();
	}
	/**
	 * 获取月份
	 * @return
	 */
	public static int getMonth(){
		return getMonth(System.currentTimeMillis());
	}
	/**
	 * 获取月份的第几天
	 * @param time
	 * @return
	 */
	public static int getDayOfMonth(long time){
		String[] strs = format(DATE_FORMAT_1,time).split("-");
		return LocalDate.of(Integer.valueOf(strs[0]), Integer.valueOf(strs[1]), Integer.valueOf(strs[2])).getDayOfMonth();
	}
	/**
	 * 获取月份的第几天
	 * @return
	 */
	public static int getDayOfMonth(){
		return getDayOfMonth(System.currentTimeMillis());
	}
	/**
	 * 比较两个时间是否同一天
	 * @param time1
	 * @param time2
	 * @return
	 */
	public static boolean isSameDay(long time1,long time2){
		return getZero(time1) == getZero(time2);
	}
	
	/**
	 * 比较两个时间是否同一月份
	 * @param time1
	 * @param time2
	 * @return
	 */
	public static boolean isSameMonth(long time1,long time2){
		String[] strs1 = format(DATE_FORMAT_1,time1).split("-");
		String[] strs2 = format(DATE_FORMAT_1,time2).split("-");
		if(!strs1[0].equals(strs2[0])){
			return false;
		}
		return strs1[1].equals(strs2[1]);
	}
	/**
	 * 比较两个时间是否同一年
	 * @param time1
	 * @param time2
	 * @return
	 */
	public static boolean isSameYear(long time1,long time2){
		String[] strs1 = format(DATE_FORMAT_1,time1).split("-");
		String[] strs2 = format(DATE_FORMAT_1,time2).split("-");
		return strs1[0].equals(strs2[0]);
	}
	/** 获取今天的零点时间 */
	public static long getZero(){
		return getZero(System.currentTimeMillis());
	}
	
	/** 获取time那天的凌晨零点时间 */
	public static long getZero(long time){
		Calendar c = Calendar.getInstance();
		c.setTime(new Date(time));
		c.set(Calendar.HOUR_OF_DAY, 0);  
		c.set(Calendar.MINUTE, 0);  
		c.set(Calendar.SECOND, 0);  
		c.set(Calendar.MILLISECOND, 0);  
        return c.getTimeInMillis();
	}
	
	/**
	 * 获取传入那天的开始时间
	 * @param time
	 * @return
	 */
	public static long getDayStartTime(long time){
		return (long) getTodayStartAndEnd(time).get("start_time");
	}
	/**
	 * 获取传入那天的结束时间
	 * @param time
	 * @return
	 */
	public static long getDayEndTime(long time){
		return (long) getTodayStartAndEnd(time).get("end_time");
	}

	/**
	 * 获取一周的开始时间
	 * @param time
	 * @return
	 */
	public static long getWeekStartTime(long time) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date(time));
		int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
		if (dayofweek == 1) {
			dayofweek += 7;
		}
		cal.add(Calendar.DATE, 2 - dayofweek);
		return getDayStartTime(cal.getTimeInMillis());
	}
 
	/**
	 * 获取一周的结束时间
	 * @param time
	 * @return
	 */
	public static long getWeekEndTime(long time){
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date(getWeekStartTime(time)));  
		cal.add(Calendar.DAY_OF_WEEK, 6); 
		return getDayEndTime(cal.getTimeInMillis());
	}
	/**
	 * 获取一年的开始时间
	 * @param time
	 * @return
	 */
	public static long getYearStartTime(long time){
		String[] strs = format(DATE_FORMAT_1,time).split("-");
		int start = Integer.valueOf(strs[0])+1;
		String formart = start+"-01-01 00:00:00";
		return parse(formart);
	}
	/**
	 * 获取一年的结束时间
	 * @param time
	 * @return
	 */
	public static long getYearEndTime(long time){
		String[] strs = format(DATE_FORMAT_1,time).split("-");
		int start = Integer.valueOf(strs[0])+1;
		String formart = start+"-12-31 23:59:59";
		return parse(formart);
	}
	/**
	 * 获取月份的开始时间
	 * @param time
	 * @return
	 */
	public static long getMonthStartTime(long time) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(getYear(time), getMonth(time) - 1, 1);
		return getDayStartTime(calendar.getTimeInMillis());
	}
 
	/**
	 * 获取月份的结束时间
	 * @param time
	 * @return
	 */
	public static long getMonthEndTime(long time) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(getYear(time), getMonth(time) - 1, 1);
		int day = calendar.getActualMaximum(5);
		calendar.set(getYear(time), getMonth(time) - 1, day);
		return getDayEndTime(calendar.getTimeInMillis());
	}

	
	/**
	 * 获取传入时间的这一天的开始时间和结束时间
	 * (如何传入为null 获取今天的开始时间和结束时间)
	 * @param time 时间戳
	 * @return map(key start_time为开始时间 key end_time为结束时间)
	 */
	@SuppressWarnings("static-access")
	private static Map<String, Object> getTodayStartAndEnd(Long time){
//		if (time!=null && time>System.currentTimeMillis()) {
//			throw new RuntimeException("the param  must not greater than current time");
//		}
		Map<String, Object> map = new HashMap<String, Object>();
		if (time != null) {
			// 获取现在的时间
			Date date = new Date(time);
			Calendar now = Calendar.getInstance();
			now.setTime(date);
			
			// 获取昨天24:00
	        Calendar strat = now;   
	        strat.set(Calendar.HOUR_OF_DAY, 0);  
	        strat.set(Calendar.MINUTE, 0);  
	        strat.set(Calendar.SECOND, 0);  
	        strat.set(Calendar.MILLISECOND, 0);  
	        Long start_time=strat.getTimeInMillis();  
	        // 获取今天24:00
	        Calendar end = now;   
	        end.add(now.DATE,1);
	        end.set(Calendar.HOUR_OF_DAY, 0);  
	        end.set(Calendar.MINUTE, 0);  
	        end.set(Calendar.SECOND, 0);  
	        end.set(Calendar.MILLISECOND, 0);  
	        Long end_time=end.getTimeInMillis();  
	        map.put("start_time", start_time);
			map.put("end_time", end_time-1);
			return map;
		}
		Calendar calendar = Calendar.getInstance();
		// 获取昨天24:00
        Calendar strat = Calendar.getInstance();   
        strat.set(Calendar.HOUR_OF_DAY, 0);  
        strat.set(Calendar.MINUTE, 0);  
        strat.set(Calendar.SECOND, 0);  
        strat.set(Calendar.MILLISECOND, 0);  
        Long start_time=strat.getTimeInMillis();  
        // 获取今天24:00
        Calendar end = Calendar.getInstance();   
        end.add(calendar.DATE,1);
        end.set(Calendar.HOUR_OF_DAY, 0);  
        end.set(Calendar.MINUTE, 0);  
        end.set(Calendar.SECOND, 0);  
        end.set(Calendar.MILLISECOND, 0);  
        Long end_time=end.getTimeInMillis();  
        map.put("start_time", start_time);
		map.put("end_time", end_time);
        return map;
	}


	/**
	 * 取时间戳
	 *
	 * @param time
	 * @return
	 * @throws ParseException
	 */
	public static long parse(String time){
		try {
			return parse(DATE_FORMAT_4,time);
		} catch (Exception e) {
			return parse(DATE_FORMAT_1,time);
		}
	}
	/**
	 * 取时间戳
	 *
	 * @param time
	 * @return
	 * @throws ParseException
	 */
	public static long parse(SimpleDateFormat f, String time){
		try {
			return f.parse(time).getTime();
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 取某几小时前（或后）的时间
	 * @param hour 小时数（正数为取后几小时，负数为取前小时）
	 * @return
	 */
	public static long sumHour(long time,int hour){
		return time+(1000*60*60*hour);
	}
	
	/**
	 * 取某几小时前（或后）的时间
	 * @param hour 小时数（正数为取后几小时，负数为取前小时）
	 * @return
	 */
	public static long sumHour(int hour){
		return sumHour(System.currentTimeMillis(),hour);
	}

	/**
	 * 计算两个时间相差小时数
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differHour(long time1,long time2){
		long time = (time1 -time2)/oneHourTime;
		return Integer.valueOf((time+"").replace("-", ""));
	}
	/**
	 * 计算两个时间相差小时数(默认格式)
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differHour(String time1,String time2){
		return differHour(time1,DATE_FORMAT_4, time2,DATE_FORMAT_4);
	}
	/**
	 * 计算两个时间相差小时数
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differHour(String time1,SimpleDateFormat format1,String time2,SimpleDateFormat format2){
		long parseTime1 = parse(format1, time1);
		long parseTime2 = parse(format2, time2);
		return differHour(parseTime1, parseTime2);
	}
	
	/**
	 * 计算两个时间相差天数
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differDay(long time1,long time2){
		long time = (time1 -time2)/oneDayTime;
		return Integer.valueOf((time+"").replace("-", ""));
	}
	/**
	 * 计算两个时间相差天数(默认格式)
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differDay(String time1,String time2){
		return differDay(time1,DATE_FORMAT_4, time2,DATE_FORMAT_4);
	}
	/**
	 * 计算两个时间相差天数
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differDay(String time1,SimpleDateFormat format1,String time2,SimpleDateFormat format2){
		long parseTime1 = parse(format1, time1);
		long parseTime2 = parse(format2, time2);
		return differDay(parseTime1, parseTime2);
	}
	
	/**
	 * 计算两个时间相差星期数
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differWeek(long time1,long time2){
		long time = (time1 -time2)/oneWeekTime;
		return Integer.valueOf((time+"").replace("-", ""));
	}
	/**
	 * 计算两个时间相差星期数(默认格式)
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differWeek(String time1,String time2){
		return differWeek(time1,DATE_FORMAT_4, time2,DATE_FORMAT_4);
	}
	/**
	 * 计算两个时间相差星期数
	 * @param time1	时间1
	 * @param time2	时间2
	 * @return
	 */
	public static int differWeek(String time1,SimpleDateFormat format1,String time2,SimpleDateFormat format2){
		long parseTime1 = parse(format1, time1);
		long parseTime2 = parse(format2, time2);
		return differWeek(parseTime1, parseTime2);
	}
	/**
	 * @param format 格式化对象
	 * @param time   时间
	 * @return 格式化后的日期
	 */
	public static String format(SimpleDateFormat format, long time) {
		return format.format(time);
	}
	/**
	 * 返回格式化后的日期（yyyy-MM-dd HH:mm:ss）
	 *
	 * @param format 格式化对象
	 * @param time   时间
	 * @return 格式化后的日期
	 */
	public static String format(long time){
		return DATE_FORMAT_4.format(time);
	}
}
